<template>
  <div>
    <h3 class="title">（大文件）切片上传</h3>
    <div class="border_dot">
      <form id="formsp">
        <input
          ref="fileRef"
          type="file"
          style="display: none"
          accept=".png,.jpg,.jpeg,.zip"
        />
      </form>
      <button class="btn select_btn btn_sel_split" @click="handleFile">
        选择文件
      </button>
      <button class="btn update_btn btn_up_split" @click="handleUpdate">
        上传
      </button>
      <div>请上传PNG/JPG/JPEG/ZIP类型图片</div>
      <div class="file_item_wrap" v-if="file">
        <span class="file_name">{{ file.name }}</span>
        <span class="file_remove" @click="handleRemove">移除</span>
      </div>
      <Progress v-if="progress > 0" :value="progress" />
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref } from "vue";
import SparkMd5 from "spark-md5";
import Progress from "./Progress.vue";
import { updateFileSplit, mergeFile } from "@/api/update";

const fileRef = ref<null | HTMLInputElement>(null);
const file = ref<null | File>(null);
const progress = ref(0);

async function handleUpdate() {
  if (!file.value) {
    alert("请选择文件");
    return;
  }
  const selectBtn = document.querySelector(".btn_sel_split");
  const updateBtn = document.querySelector(".btn_up_split");
  selectBtn?.setAttribute("disabled", "disabled");
  updateBtn?.setAttribute("loading", "loading");
  const fileList = await fileSlice(file.value);
  console.log(fileList, "fileList");
  
  const bf = await changeBuffer(file.value);
  const sparkMd5 = new SparkMd5.ArrayBuffer();
  sparkMd5.append(bf);
  const filename = sparkMd5.end();
  const sufixname = file.value.name.split(".").pop();

  const files = fileList.map((e, i) => {
    return new Promise((resolve, reject) => {
      const formData = new FormData();
      formData.append("file", e.file);
      updateFileSplit<
        {
          file: FormData;
          filename: string;
          sufixname: string;
          dirname: string;
        },
        { type: number; path: string }
      >({
        file: formData,
        filename: `${filename}_${i}`,
        sufixname,
        dirname: filename,
      })
        .then(resolve)
        .catch(reject);
    });
  });
  try {
    await Promise.all(files);
    await mergeFile<{filename: string, sufixname: string}>({ filename, sufixname });
    alert("上传成功");
  } catch (error) {
    alert("上传失败");
  } finally {
    (document.querySelector("#formsp") as HTMLFormElement).reset();
    file.value = null;
    selectBtn?.removeAttribute("disabled");
    updateBtn?.removeAttribute("loading");
  }
}

async function fileSlice(file: File) {
  let idx = 0;
  let maxLength = 24 * 1024 * 1024;
  let count = Math.ceil(file.size / maxLength);
  const fileList = [];
  if (count > 50) {
    count = 50;
    maxLength = file.size / count;
  }
  while (idx < count) {
    const chunk = file.slice(idx * maxLength, (idx + 1) * maxLength) as File;
    fileList.push({
      file: chunk,
    });
    idx++;
  }
  return fileList;
}

function changeBuffer(file: File) {
  return new Promise((resolve, reject) => {
    const fr = new FileReader();
    fr.readAsArrayBuffer(file);
    fr.onload = (ev: Event) => {
      const bf = (ev.target as FileReader).result;
      resolve(bf);
    };
    fr.onerror = reject;
  });
}

function handleFile() {
  fileRef.value?.click();
}
function handleRemove() {
  (document.querySelector("#formsp") as HTMLFormElement).reset();
  file.value = null;
}
onMounted(() => {
  fileRef.value?.addEventListener("change", (ev: Event) => {
    file.value = (ev.target as HTMLInputElement).files![0];
  });
});
</script>

<style></style>
